#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/soundcard.h>
#include <sys/ioctl.h>
#include <sys/signal.h>
#include <sys/mman.h>
#include <unistd.h>
#include <linux/fb.h>
#include <fcntl.h>
#include <sys/time.h> // struct itimeral. setitimer()
#include <pthread.h>

#define FLCD_GET_DATA_SEP   0x46db
#define FLCD_GET_DATA       0x46dc
#define FLCD_SET_FB_NUM     0x46dd
#define FLCD_SWITCH_MODE    0x46de
#define FLCD_CLOSE_PANEL    0x46df

#define HZ  10

struct flcd_data
{
    unsigned int buf_len;
    unsigned int uv_offset;
    unsigned int frame_no;
	unsigned int mp4_map_dma[10];
};

struct fb_buffer_t {
    unsigned char *data[3];
};

int fbfd=0;
int frame_number=0,fb_display=0;
volatile int ridx,widx;
unsigned char *mmap_addr;
struct fb_var_screeninfo vinfo;
struct fb_buffer_t fb_buffer[10];   //give 10 frame buffer structure
struct flcd_data f_data;
char *print_string[10]={""," ","  ","   ","    ","     ","      ","       ","        ","         "};

    int width,height;
    int fbn=0; //init to 0
    FILE *fin  = 0;
    FILE *fout = 0;
    
    char filename[20];

    int res = 0;
    int framerate=20;
    //implement citical section
    pthread_mutex_t job_mutex = PTHREAD_MUTEX_INITIALIZER;
    int g_fr;

static void sig_show(void) 
{
    if (ridx>9)
        ridx =1;
    fb_display=ridx; 
    fflush(stdout);
    sprintf(filename,"/tmp/display%d.yuv",fb_display);  
    fin=fopen(filename,"rb");
    if(!fin)
    {
        printf("Fail to open %s\n",filename);
    }
    fread(fb_buffer[fb_display].data[0],width*height,1,fin);   //read Y
    fread(fb_buffer[fb_display].data[1],width*height/4,1,fin); //read U
    fread(fb_buffer[fb_display].data[2],width*height/4,1,fin); //read V
    ioctl(fbfd,FLCD_SET_FB_NUM,&fb_display);
    ridx++;
    fclose(fin);
}

static void sig_int(void) 
{
	printf("Ctrl+C to end program\n");
	fb_display=0;
    ioctl(fbfd,FLCD_SET_FB_NUM,&fb_display);
    munmap(mmap_addr,f_data.frame_no*f_data.buf_len);
    exit(0);
}

void showhint() 
{
    printf("lcd_display version 0.1, Copyright (c) 2007 Faraday MBU VS\n");
    printf("usag: lcd_display -f framerate\n\n");
}

void getparameter(int i_argc,char **argvv) 
{
    if ( strstr(argvv[1],"-f")!=NULL ) {
        g_fr = atoi(argvv[2]);
    } 
    else 
        showhint();      
}

int main(int argc, char **argv)
{
    int i;
    struct itimerval tick;   
    long tmp; 

	fbfd = open("/dev/fb0", O_RDWR);
	if (!fbfd)
	{
	    printf("LCD Error: cannot open framebuffer device.\n");
		exit(0);
	}

  	if (ioctl(fbfd,FLCD_SET_FB_NUM,&fbn)<0) 
  	{
   	    printf("Fail to set fb num\n");
   	    exit(0);
   	}
        
    // Get variable screen information
    if (ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo))
    {
        printf("LCD Error: cannot reading variable information.\n");
		exit(0);
    }

	if (ioctl(fbfd, FLCD_GET_DATA_SEP, &f_data) < 0)
	{
		printf("LCD Error: can not operate 0x%x\n", FLCD_GET_DATA_SEP);
		exit(0);
	}

	printf("f_data:buf_len=%d,uv_offset=%d,frame_no=%d\n", f_data.buf_len, f_data.uv_offset, f_data.frame_no);
	
    frame_number = f_data.frame_no;
    //printf("frame_number:%d; f_data.buf_len:%d\n",frame_number,f_data.buf_len);

	mmap_addr = (unsigned char *)mmap(0, f_data.frame_no*f_data.buf_len, PROT_READ|PROT_WRITE, MAP_SHARED, fbfd, 0);
	if(mmap_addr<0) 
	{
	    printf("Fail to mmap flcd frame buffer");
	    exit(0);
	}   

	width  = vinfo.xres;
    height = vinfo.yres;
	printf("LCD width:%d height:%d\n",width,height);
	
	fout = fopen("/tmp/display1.yuv", "wb");
	fwrite((unsigned char *)((unsigned int)mmap_addr+(f_data.buf_len)*0), width*height, 1, fout);
	fwrite((unsigned char *)((unsigned int)mmap_addr+(f_data.buf_len)*0)+f_data.uv_offset, width*height/4, 1, fout);
	fwrite((unsigned char *)((unsigned int)mmap_addr+(f_data.buf_len)*0)+f_data.uv_offset+(f_data.uv_offset/4), width*height/4, 1, fout);		
	fclose(fout);
	
	return 1;
	
	
	
#if 0	
	for(i=0;i<frame_number;i++) {
        printf("Picture %d from address 0x%x\n",i,(unsigned char *)((unsigned int)mmap_addr+(i*f_data.buf_len)));
        fb_buffer[i].data[0]=(unsigned char *)((unsigned int)mmap_addr+(i*f_data.buf_len));
        fb_buffer[i].data[1]=(unsigned char *)((unsigned int)mmap_addr+(i*f_data.buf_len))+f_data.uv_offset;
        fb_buffer[i].data[2]=(unsigned char *)((unsigned int)mmap_addr+(i*f_data.buf_len))+f_data.uv_offset+(f_data.uv_offset/4);
	}

    if(signal(SIGINT,(void *)sig_int)==SIG_ERR)
       	printf("signal ctrl+c error\n");

    signal(SIGALRM, (void *)sig_show);  // Register sig_show to SIGALRM
      

       	
/* The First Picture (i=1) */
    widx=1;
    sprintf(filename,"/tmp/display%d.yuv",widx);
    fin=fopen(filename,"rb");
    if(!fin) {
        printf("Fail to open %s\n",filename);
        return;
    }
    fread(fb_buffer[widx].data[0],width*height,1,fin);   //read Y
    fread(fb_buffer[widx].data[1],width*height/4,1,fin); //read U
    fread(fb_buffer[widx].data[2],width*height/4,1,fin); //read V
    fclose(fin);
    fbn=1;   
    ridx=2;
    
  	if (ioctl(fbfd,FLCD_SET_FB_NUM,&fbn)<0) {
   	    printf("Fail to set fb num\n");
   	    exit(0);
   	}

    // Initialize struct
    memset(&tick, 0, sizeof(tick));
    // Timeout to run function first time
    tick.it_value.tv_sec = 0;  // sec

    if (g_fr == 30) {
        tick.it_value.tv_usec = 900000 / g_fr;
        printf("framerate is:%d\n",g_fr);
    }
    else if (framerate > 0){
        tick.it_value.tv_usec = 990000 / g_fr;
        printf("framerate is:%d\n",g_fr);
    }  
    else {
        tick.it_value.tv_usec = 0;
        printf("disable timer!\n");
    }      
    // Interval time to run function
    tick.it_interval = tick.it_value;
    // Set timer, ITIMER_REAL : real-time to decrease timer,
    //                          send SIGALRM when timeout
   	//Set timer
    res = setitimer(ITIMER_REAL, &tick, NULL);
    if (res) {
        printf("Set timer failed!!\n");
    }
    
// Start from the second Picture (i=2)
    widx++;
    
    printf("Please use [CTRL-C] to exit program!\n");
    fflush(stdout);
 
    while (1) 
    {
        usleep(1);
        select(0, NULL, NULL, NULL, NULL);  	      
        //pause();
    }
#endif    
}

